﻿// See https://aka.ms/new-console-template for more information
//观察者模式
//观察者模式（Observer Pattern）是一种行为型设计模式，他定义了对象之间的一对多的依赖关系，使得当一个对象的状态发生改变时，所有依赖他的对象都会自动的得到通知并更新。
//在软件系统中，对象并不是鼓励存在的，一个对象的行为的改变可能会导致一个或多个其他与之相关的对象行为发生改变，他们之间将产生联动，所谓牵一发而动全身。为了更好的描述对象之间存在的这种一对一或者一对多的关系，观察者模式应运而生，他定义了对象之间一种一对多的依赖关系，让一个对象改变可以影响其他对象。
//在日产生活中，交通灯指挥着日益拥挤的城市交通，当红灯亮起时，来往的汽车将停止，绿灯亮起时，汽车可以继续前进。在这个过程中，交通灯信号是汽车的观察目标，而汽车是交通的的观察者。随着交通灯的变化，汽车的行为也发生了变化，一盏交通灯可以指挥多辆汽车。
//观察者模式主要由以下几个角色组成
//·Subjet(主题)：他是被观察的对象，当他的状态发生改变时，会通知所有观察者。
//·Observer（观察者）：他定义了一个更新接口，当主题的状态发生改变时，他的update方法会被调用。
//·ConcreteSubject（具体主题）：他是具体的被观察对象，当他的状态发生改变时，会通知所有注册的观察者。
//·ConcreteObserver（具体观察者）：他是具体的观察者对象，当接收刀来自主题的通知时，他的状态的会自动更新。

Product product = new Product("IPhone",10);

User user1 = new User("user1");
User user2 = new User("user2");
User user3 = new User("user3");

product.AddObserver(user1);
product.AddObserver(user2);
product.AddObserver(user3);

product.UpdateStock(5);//通知所有关注IPhone的用户
product.RemoveObserver(user1);
product.UpdateStock(1);


Console.WriteLine("Hello, World!");

//假设有一个电商平台，当某个商品的库存发生变化时，需要通知所有关注该商品的用户
//Subject接口，表示商品
public interface ISubject
{
    void AddObserver(IObserver observer);//添加观察者

    void RemoveObserver(IObserver observer);//删除观察者

    void NotifyObservers();//通知观察者
}

//ConcreteSubject类，表示具体商品
public class Product : ISubject
{
    private string name;
    private int stock;
    private List<IObserver> observers = new List<IObserver>();

    public Product(string name, int stock)
    {
        this.name = name;
        this.stock = stock;
    }

    public void AddObserver(IObserver observer)
    {
        observers.Add(observer);
    }

    public void RemoveObserver(IObserver observer)
    {
        observers.Remove(observer);
    }

    public void NotifyObservers()
    {
        foreach (var observer in observers)
        {
            observer.Update(this);
        }
    }

    public void UpdateStock(int newStock)
    {
        if (newStock != stock)
        {
            stock = newStock;
            NotifyObservers();
        }
    }

    public int GetStock()
    {
        return stock;
    }
    public string GetName()
    {
        return name;
    }
}

//Observer接口，表示用户
public interface IObserver
{
    void Update(Product product);//更新方法
}

//ConcreteObserver类，表示具体的用户
public class User : IObserver
{
    private string name;

    public User(string name)
    {
        this.name = name;
    }

    public void Update(Product product)
    {
        Console.WriteLine("{0}received notification:{1}'s stock is {2}", name, product.GetName(), product.GetStock());
    }
}